home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / standards / sgml / nist / parse3 / diinit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-13  |  24.2 KB  |  663 lines

  1. /* National Institute of Standards and Technology (NIST)
  2. /* National Computer System Laboratory (NCSL)
  3. /* Office Systems Engineering (OSE) Group
  4. /* ********************************************************************
  5. /*                            D I S C L A I M E R
  6. /*                              (March 8, 1989)
  7. /*  
  8. /* There is no warranty for the NIST NCSL OSE SGML parser and/or the NIST
  9. /* NCSL OSE SGML parser validation suite.  If the SGML parser and/or
  10. /* validation suite is modified by someone else and passed on, NIST wants
  11. /* the parser's recipients to know that what they have is not what NIST
  12. /* distributed, so that any problems introduced by others will not
  13. /* reflect on our reputation.
  14. /* 
  15. /* Policies
  16. /* 
  17. /* 1. Anyone may copy and distribute verbatim copies of the SGML source
  18. /* code as received in any medium.
  19. /* 
  20. /* 2. Anyone may modify your copy or copies of SGML parser source code or
  21. /* any portion of it, and copy and distribute such modifications provided
  22. /* that all modifications are clearly associated with the entity that
  23. /* performs the modifications.
  24. /* 
  25. /* NO WARRANTY
  26. /* ===========
  27. /* 
  28. /* NIST PROVIDES ABSOLUTELY NO WARRANTY.  THE SGML PARSER AND VALIDATION
  29. /* SUITE ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
  30. /* EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  31. /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  32. /* THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS
  33. /* WITH YOU.  SHOULD THE SGML PARSER OR VALIDATION SUITE PROVE DEFECTIVE,
  34. /* YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  35. /* 
  36. /* IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL NIST BE LIABLE FOR
  37. /* DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL,
  38. /* INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
  39. /* INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
  40. /* BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
  41. /* FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY
  42. /* NIST) THE PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF
  43. /* SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
  44. */
  45.  
  46. /************************************************************************/
  47. /*   TITLE:          SGML PARSER                                        */
  48. /*   SYSTEM:         DOCUMENT PROCESSOR                                 */
  49. /*   SUBSYSTEM:                                                         */
  50. /*   SOURCE FILE:    DIINIT.C                                           */
  51. /*   AUTHOR:         Steven Lindeman, Fred Maples                       */
  52. /*                                                                      */
  53. /*   DATE CREATED:                                                      */
  54. /*   LAST MODIFIED:                                                     */
  55. /*                                                                      */
  56. /*                  REVISIONS                                           */
  57. /*   WHEN      WHO            WHY                                       */
  58. /************************************************************************/
  59. #include <stdio.h>
  60. #include <fcntl.h>
  61. #include "didefs.h"
  62. #include "diglobal.h"
  63.  
  64. /*------------------------------------------------------*/
  65. /*         C H E C K O P T       */
  66. /* Reads the command line for document name to  */
  67. /* be parsed and options to be applied.      */
  68. /*------------------------------------------------------*/
  69. void checkopt(argc,argv,path,delete_temps,bld_ctr)
  70. int argc;
  71. char *argv[],path[];
  72. BOOLEAN *delete_temps,*bld_ctr;
  73. {
  74.    FILE *fopen();
  75.    int thisarg,fprintf(),fputc();
  76.    long seekpos,atol();
  77.    void semantic();
  78.    char *cptr;
  79.  
  80.    if (argc < 3) {
  81.       printf("INVALID COMMAND LINE PARAMETERS. Valid parameters are:\n");
  82.       printf("PARSE3 <input-doc> -P<###> -T<path-name> -3<#> -N -F");
  83.       exit(99);
  84.    }
  85.    if ((indoc=fopen(argv[1],"rb")) == NULL) {  /* machine dependent */
  86.       printf("Unknown source document file '%s'\n",argv[1]);
  87.       exit(99);
  88.    }
  89. #ifdef FRED
  90.    ctrfile = get_char_mem(strlen(argv[1])+4);
  91.    strcpy(ctrfile,argv[1]);
  92.  
  93.    for (cptr=ctrfile+strlen(ctrfile); *cptr!='.'&& *cptr!=DIR_SEPERATOR; cptr--);
  94.    if (*cptr == '.')
  95.       strcpy(cptr,".CTR");
  96.    else
  97.       strcat(ctrfile,".CTR");
  98. #else
  99.    ctrfile = "CTRFILE.CTR";
  100. #endif
  101.    fpstack[fpindx=0] = indoc;
  102.    seekpos = atol(argv[2]+2);
  103.    thisarg = 3;  
  104.    *bld_ctr = TRUE;
  105.    applic = nullfnc;
  106.    our_fprintf = print_ctr = fprintf;
  107.    our_fputc = put_ctr = fputc;
  108.    path[0] = '\0';  
  109.    *delete_temps = TRUE;
  110.  
  111.    while(argc > thisarg) {
  112.       switch(*(argv[thisarg]+1)) {  
  113.       case 'T':
  114.          strcpy(path,argv[thisarg]+2);
  115.          break;
  116.       case 'N':
  117.          *bld_ctr = FALSE;
  118.          print_ctr = put_ctr = nullfnc;
  119.          break;
  120.       case 'F':
  121.          *delete_temps = FALSE;
  122.          break;
  123.       case 'S':
  124.          applic = semantics;
  125.          break;
  126.       case 'H':
  127.          printf("\n                      SGML Document Element Parser\n");
  128.          printf("         Parses document elements in conformance with ISO 8879\n");
  129.          printf("\n          ------------ Version 0.16  08-Jul-87 -------------\n");
  130.          printf("                    Assuming Core Concrete Syntax\n");
  131.          printf("          --------------------------------------------------\n\n");
  132.          printf("Parsing document... %s\n",argv[1]);
  133.          break;
  134.       }
  135.       thisarg++;
  136.    }
  137.    fseek(indoc,seekpos,0);   /* seekpos is offset from file beginning */
  138.  
  139.    if (*bld_ctr && (ctrfp=fopen(ctrfile,"w")) == NULL) {
  140.       printf("Unable to create CTR output file '%s'.\n",ctrfile);
  141.       exit(99);
  142.    }
  143.    (*print_ctr)(ctrfp,"Canonical Test Result:");
  144.    return;
  145. }
  146.  
  147. /*------------------------------------------------------*/
  148. /*               C H A N G E _ T R E E S                */
  149. /*     This routine is used to ensure that 'token' is   */
  150. /*     is a valid index into the symbol table array.    */
  151. /*     All of the trees and AND lists are traversed     */
  152. /*     and the 'nodeid's are replaced with the corr-  */
  153. /*     esponding new token indexes.       */
  154. /*------------------------------------------------------*/
  155. void change_trees(ptr,numsym)
  156. TNODE *ptr;
  157. int numsym;
  158. {
  159.    TNODE *currp;
  160.    register short i;
  161.  
  162.    if (ptr != NULL)
  163.       if (ptr->nodeid == AND) {
  164.          currp = ptr->u.llptr;
  165.          while(currp->next != ptr->u.llptr) {
  166.             change_trees(currp,numsym);
  167.             currp = currp->next;
  168.          }
  169.          change_trees(currp,numsym);
  170.       }
  171.       else {
  172.          change_trees(ptr->left,numsym);
  173.          change_trees(ptr->u.right,numsym);
  174.          for (i=0; i<numsym && !ptr->changed; i++)
  175.             if (ptr->nodeid == symtable[i].tokenid) {
  176.                ptr->nodeid = i;
  177.                ptr->changed = TRUE;
  178.             }
  179.       }
  180.    return;
  181. }
  182.  
  183. /*------------------------------------------------------*/
  184. /*               C H A N G E _ E X C E P T S            */
  185. /*     This routine is used to ensure that 'token' is   */
  186. /*     is a valid index into the symbol table array.    */
  187. /*     All of the entries in the exception lists are    */
  188. /*     replaced with the corresponding new token        */
  189. /*     indexes.                                 */
  190. /*------------------------------------------------------*/
  191. void change_excepts(headexcptr,numsym)
  192. EXCEPTDESC *headexcptr;
  193. int numsym;
  194. {
  195.    register int i;
  196.    EXCEPTDESC *excptr;
  197.  
  198.    /*  This code assumes that an exception cannot include or exclude itself */
  199.    for (i=0; i < numsym; i++) {
  200.       for (excptr=headexcptr; excptr!=NULL; excptr=excptr->nextlocal)
  201.          if (excptr->tokenid==symtable[i].tokenid && !excptr->changed) {
  202.             excptr->changed = TRUE;
  203.             excptr->tokenid = i;
  204.          }
  205.    }
  206.    return;
  207. }
  208.  
  209. /*------------------------------------------------------*/
  210. /*        B U I L D A T T R         */
  211. /* Builds a multi-linked list of attribute def- */
  212. /* initions from the input file 'attrfile.dat'. */
  213. /* A pointer to the newly built list is returned   */
  214. /* or NULL if there were no attributes found in */
  215. /* the file.               */
  216. /*------------------------------------------------------*/
  217. ATTRDESC *buildattr(attrfd)
  218. int attrfd;
  219. {
  220.    ATTRDESC *retptr,*thisptr;
  221.    unsigned numattr;
  222.    register int i,j;
  223.    char buffer[LITLEN];
  224.  
  225.    retptr = thisptr = adalloc();  /* first one */
  226.    read(attrfd,&numattr,sizeof(int));
  227.    for (i=1; i<=numattr; i++) {
  228.       memset(thisptr->attrname,'\0',NAMELEN+1);
  229.       read(attrfd,thisptr->attrname,NAMELEN);
  230.       NULLTERM(thisptr->attrname);
  231.       read(attrfd,&(thisptr->dvcode),sizeof(DECLVAL));
  232.       read(attrfd,&(thisptr->defcode),sizeof(ADFLT));
  233.       j = 0;
  234.       read(attrfd,buffer,sizeof(char));
  235.       while(buffer[j] != '\0')
  236.          read(attrfd,&(buffer[++j]),sizeof(char));
  237.       switch(thisptr->defcode) {
  238.       case A_UNFIXED:  
  239.       case A_FIXED:
  240.          thisptr->u2.currdef = get_char_mem(j+1);
  241.          strncpy(thisptr->u2.currdef,buffer,j+1);
  242.          break;
  243.       default:
  244.          thisptr->u2.currgrp = NULL; /* could set currgrp or currdef */
  245.          break;
  246.       }
  247.       thisptr->groupp = buildgroup(attrfd);
  248.       thisptr->next = (i == numattr) ? NULL : adalloc();
  249.       thisptr = thisptr->next;
  250.    }
  251.    return(retptr);
  252. }
  253.  
  254. /*------------------------------------------------------*/
  255. /*                B U I L D E X C E P T         */
  256. /* This routine builds a linked list containing */
  257. /* the inclusion or exclusion exceptions for a     */
  258. /* token.  A pointer to the newly built list is */
  259. /* returned or NULL is returned if there were no   */
  260. /* exceptions found in the file.       */
  261. /*------------------------------------------------------*/
  262. EXCEPTDESC *build_except(exceptfd)
  263. int exceptfd;
  264. {
  265.    EXCEPTDESC *curr,*retptr;
  266.    register int i;
  267.    unsigned num_except;
  268.  
  269.    retptr = NULL;
  270.    read(exceptfd,&num_except,sizeof(int));
  271.    for (i=0; i<num_except; i++) {
  272.       if (i == 0)
  273.          curr = retptr = exalloc();
  274.       else
  275.          curr = curr->nextlocal = curr->nextglobal = exalloc();
  276.       read(exceptfd,&(curr->tokenid),sizeof(int));
  277.       curr->changed = FALSE;   /* not been changed yet for new indexes */
  278.    }
  279.    if (retptr != NULL)
  280.       curr->nextlocal = curr->nextglobal = NULL;
  281.    return(retptr);
  282. }
  283.  
  284. /*------------------------------------------------------*/
  285. /*                B U I L D E N T I T Y         */
  286. /* This routine builds a linked list containing */
  287. /* the general entity names and values.  A ptr     */
  288. /* to the newly built list is returned or NULL  */
  289. /* if there were no entities found in the file. */
  290. /*------------------------------------------------------*/
  291. ENTITYDESC *build_entity(entityfd)
  292. int entityfd;
  293. {
  294.    ENTITYDESC *thisptr,*retptr;
  295.    int length;
  296.  
  297.    retptr = NULL;             /* length of reference */
  298.    while(read(entityfd,&length,sizeof(int)) > 0) { /* including ending null */
  299.       if (retptr == NULL)
  300.          thisptr = retptr = gealloc();
  301.       else
  302.          thisptr = thisptr->next = gealloc();
  303.       memset(thisptr->entityname,'\0',NAMELEN+1);
  304.       read(entityfd,thisptr->entityname,NAMELEN);  /* name of entity */
  305.       NULLTERM(thisptr->entityname);
  306.       read(entityfd,&(thisptr->entitytype),sizeof(int));
  307.       thisptr->entityvalue = get_char_mem(length);
  308.       read(entityfd,thisptr->entityvalue,length);  /* entity reference that */
  309.    }                    /* null terminated       */
  310.    if (retptr != NULL)
  311.       thisptr->next = NULL;
  312.    return(retptr);
  313. }
  314.  
  315. /*------------------------------------------------------*/
  316. /*       B U I L D G R O U P        */
  317. /* Builds a singly linked list, to be part of the  */
  318. /* multi-linked list described in BUILDATTR, which */
  319. /* contains the members of the name token group.   */
  320. /* If the number in the group equals zero, that is */
  321. /* there is no group, BUILDGROUP returns NULL   */
  322. /* else a pointer to newly build list is returned. */
  323. /*------------------------------------------------------*/
  324. GROUPDESC *buildgroup(attrfd)
  325. int attrfd;
  326. {
  327.    GROUPDESC *retptr,*thisptr;
  328.    unsigned numgroup;
  329.    register int i;
  330.  
  331.    read(attrfd,&numgroup,sizeof(int));
  332.    if (numgroup == 0)
  333.       retptr = NULL;
  334.    else
  335.       retptr = thisptr = gralloc();  /* get first one */
  336.    for (i=1; i<=numgroup; i++) {
  337.       memset(thisptr->groupname,'\0',NAMELEN+1);
  338.       read(attrfd,thisptr->groupname,NAMELEN);
  339.       NULLTERM(thisptr->groupname);
  340.       thisptr->next = (i == numgroup) ? NULL : gralloc();
  341.       thisptr = thisptr->next;
  342.    }
  343.    return(retptr);
  344. }
  345.  
  346. /*--------------------------------------------------------------*/
  347. /*                   B U I L D _ T A B L E                      */
  348. /* This routine is done as part of the initialization */
  349. /* process.  It sets up memory for the symbol table of   */
  350. /* generic identifiers and goes off to build the content */
  351. /* model for each one.              */
  352. /*--------------------------------------------------------------*/
  353. build_table(path)
  354. char path[];
  355. {
  356.    char filename[PATHLEN];
  357.    register int i;
  358.    int tablefd,count;
  359.    SYMBREC srec;
  360.  
  361.    sprintf(filename,"%s%s",path,"dtdfile.sgm");
  362.    if ((tablefd=open(filename,O_RDONLY)) == -1)   /* open file */
  363.       ourexit(2,"Unknown document type definition file\n");
  364.  
  365.    read(tablefd,&count,sizeof(int));      /* read number of symbols in table */
  366.    read(tablefd,&rootid,sizeof(int));      /* read the root symbol id */
  367.  
  368.    if ((symtable=(STPTR) malloc((count)*sizeof(STENTRY))) == NULL)
  369.       ourexit(2,"\nInsufficient memory in parse3.\n");
  370.  
  371.    for (i=0; i < count; i++) {          /* read each entry into symtable */
  372.       read(tablefd,&srec,sizeof(SYMBREC));
  373.       memset(symtable[i].nametoken,'\0',NAMELEN+1);
  374.       strncpy(symtable[i].nametoken,srec.Sname,NAMELEN);
  375.       NULLTERM(symtable[i].nametoken);
  376.       symtable[i].tokenid = srec.Sid;
  377.       /* minimization, NONE, START, END, BOTH */
  378.       symtable[i].miniexcept = srec.Smin;
  379.       symtable[i].adptr = NULL;      /* assumes there are no attributes */
  380.       symtable[i].inclusion = symtable[i].exclusion = NULL;
  381.       symtable[i].content_type = ELEMENT_CONTENT;  /* just an assumption */
  382.       symtable[i].num_open = 0;
  383.    }
  384.  
  385.    for (i=0; i < count; i++)                 /* build the content model for each element */
  386.       symtable[i].cmptr = buildtree(tablefd,&dontcare,&(symtable[i].content_type));
  387.    if (close(tablefd) != 0) {
  388.       printf("Unable to close 'dtdfile.sgm'.\n");
  389.       exit(99);
  390.    }
  391.    return(count);
  392. }
  393.  
  394. /*------------------------------------------------------*/
  395. /*                 B U I L D T R E E                     */
  396. /*                                                 */
  397. /*    Called by   :INIT, BUILDTREE                 */
  398. /*                                                 */
  399. /*    Returns     :ptr to the root node in         */
  400. /*                 the tree.                       */
  401. /*                                                 */
  402. /*    Builds the content models as binary          */
  403. /*      trees for the given symbol table           */
  404. /*      entry.                                     */
  405. /*------------------------------------------------------*/
  406. TNODE *buildtree(tablefd,oiopt,content_type)
  407. int tablefd;
  408. BOOLEAN *oiopt;
  409. int *content_type;
  410. {
  411.    TNODE *ptr,*currp;
  412.    DTDREC drec;
  413.    unsigned numands;
  414.    register int i;
  415.    BOOLEAN leftoiopt,rightoiopt,listoiopt;
  416.  
  417.    /* If a given node has an optional occurrence indicator,
  418.          then everything below is essentially optional.  */
  419.  
  420.    read(tablefd,&drec,sizeof(DTDREC));    /* reads nodeid & occurind */
  421.  
  422.    ptr = talloc();          /* build a node */
  423.    ptr->nodeid = drec.Dtoken;
  424.    ptr->copyoi = ptr->occurind = drec.Doi;
  425.    ptr->contreq = ptr->copycontreq = drec.Dcontreq;
  426.    ptr->changed = ptr->contref_attr = FALSE;
  427.    switch(ptr->nodeid) {
  428.    case COMMA:
  429.       ptr->left = buildtree(tablefd,&leftoiopt,content_type);
  430.       ptr->u.right = buildtree(tablefd,&rightoiopt,content_type);
  431.       if ((leftoiopt&&rightoiopt) && (testoi(ptr)==PLUS||testoi(ptr)==ONE)) {
  432.          *oiopt = TRUE;
  433.          reduceoi(ptr);
  434.       }
  435.       else
  436.          *oiopt = FALSE;
  437.       break;
  438.    case OR:
  439.       ptr->left = buildtree(tablefd,&leftoiopt,content_type);
  440.       ptr->u.right = buildtree(tablefd,&rightoiopt,content_type);
  441.       if ((leftoiopt||rightoiopt) && (testoi(ptr)==PLUS||testoi(ptr)==ONE)) {
  442.          *oiopt = TRUE;
  443.          reduceoi(ptr);
  444.       }
  445.       else
  446.          *oiopt = FALSE;
  447.       break;
  448.    case AND:
  449.       read(tablefd,&numands,sizeof(int));  /* number of elem in & group */
  450.       currp = ptr->u.llptr = buildtree(tablefd,&listoiopt,content_type);
  451.       *oiopt = listoiopt;  /* first node in list */
  452.       for (i=1; i<numands; i++) {
  453.          currp->next = buildtree(tablefd,&listoiopt,content_type);
  454.          if (listoiopt == FALSE)  /* once false, can never change */
  455.             *oiopt = FALSE;
  456.          currp = currp->next;
  457.       }
  458.       currp->next = ptr->u.llptr;    /* make it circular */
  459.       if ((*oiopt==TRUE) && (testoi(ptr)==PLUS||testoi(ptr)==ONE))
  460.          reduceoi(ptr);
  461.       break;
  462.    default:
  463.       if (ptr->nodeid < 0)     /* ANY, CDATA, RCDATA, PCDATA, or EMPTY */
  464.          *content_type = OTHER_CONTENT;
  465.       *oiopt = (testoi(ptr) == OPT) ? TRUE : FALSE;
  466.       ptr->left = NULL;   /* null left pointer */
  467.       ptr->u.right = NULL;  /* null right pointer */
  468.       break;
  469.    }
  470.    return(ptr);
  471. }
  472.  
  473. /*--------------------------------------------------------------*/
  474. /*                 E X P A N D _ A N Y                      */
  475. /* This routine expands the declaration for content of   */
  476. /* ANY to mixed content in which parsed character data   */
  477. /* and any elements defined in the same DTD are allowed. */
  478. /* A pointer to the newly built tree is returned.     */
  479. /*--------------------------------------------------------------*/
  480. TNODE *expand_any(numsym)
  481. int numsym;
  482. {
  483.    register TNODE *retptr;
  484.    static int thissym = -1;
  485.  
  486.    retptr = talloc();
  487.    retptr->nodeid = OR;
  488.    retptr->contreq = retptr->copycontreq = C_NEVERO;   /* not contextually required */
  489.    retptr->changed = FALSE;
  490.    retptr->contref_attr = FALSE;
  491.  
  492.    retptr->left = talloc();
  493.    retptr->left->changed = retptr->left->contref_attr = FALSE;
  494.    retptr->left->contreq =  retptr->left->copycontreq = C_NEVERO;
  495.  
  496.    switch(thissym) {
  497.    case -1:
  498.       retptr->left->nodeid = PCDATA;
  499.       retptr->occurind = retptr->copyoi = '*';
  500.       retptr->left->occurind = '*';
  501.       break;
  502.    default:
  503.       retptr->left->nodeid = symtable[thissym].tokenid;
  504.       retptr->occurind = retptr->copyoi = '?';
  505.       retptr->left->occurind = retptr->left->copyoi = '?';
  506.       break;
  507.    }
  508.    retptr->left->left = retptr->left->u.right = NULL;
  509.    if (++thissym < numsym-1)
  510.       retptr->u.right = expand_any(numsym);
  511.    else {
  512.       retptr->u.right = talloc();
  513.       retptr->u.right->nodeid = symtable[thissym].tokenid;
  514.       retptr->u.right->left = retptr->u.right->u.right = NULL;
  515.       retptr->u.right->changed = retptr->u.right->contref_attr = FALSE;
  516.       retptr->u.right->contreq = retptr->u.right->copycontreq = C_NEVERO;
  517.       retptr->u.right->occurind = retptr->u.right->occurind = '?';
  518.       thissym = -1;
  519.    }
  520.    return(retptr);
  521. }
  522.  
  523. /*-------------------------------------------------------------------*/
  524. /*                          I N I T                                  */
  525. /*     Called by   :MAIN                                             */
  526. /*     Returns     :VOID                                             */
  527. /*                                                                   */      
  528. /*     Initializes :symbol table, binary tree, number of symbols     */
  529. /*                    rootid                                         */
  530. /*                                                                   */
  531. /*     The symbol table is an array of structures.  The structure    */
  532. /*       has three members; nametoken, tokenid, and cmptr.           */
  533. /*     The nametoken is a character array which contains the name    */
  534. /*       of a token.                                                 */
  535. /*     The tokenid is an integer used to uniquely represent the      */
  536. /*       nametoken.                                                  */
  537. /*     The cmptr (content model pointer) is an integer pointer that  */
  538. /*       points to the root node of a binary tree.  The binary tree  */
  539. /*       is used the represent the content model associated with     */
  540. /*       each nametoken.                                             */
  541. /*-------------------------------------------------------------------*/
  542. void init(numsym,genthead,penthead,path)
  543. int *numsym;
  544. ENTITYDESC **genthead,**penthead;
  545. char path[];
  546. {
  547.    BOOLEAN root_changed=FALSE;
  548.    int gentityfd,attrfd,tokenids[GRPCNT],exceptfd,except_elt,pentityfd;
  549.    unsigned num_elem;
  550.    register int i;
  551.    char filename[PATHLEN];
  552.  
  553.    sprintf(filename,"%s%s",path,"attrfile.sgm");
  554.    if ((attrfd=open(filename,O_RDONLY)) == -1)
  555.       ourexit(2,"Unknown attribute file\n");
  556.  
  557.    sprintf(filename,"%s%s",path,"greffile.sgm");
  558.    if ((gentityfd=open(filename,O_RDONLY)) == -1)
  559.       ourexit(2,"Unknown general entity file\n");
  560.  
  561.    sprintf(filename,"%s%s",path,"preffile.sgm");
  562.    if ((pentityfd=open(filename,O_RDONLY)) == -1)
  563.       ourexit(2,"Unknown parameter entity file\n");
  564.  
  565.    sprintf(filename,"%s%s",path,"except.sgm");
  566.    if ((exceptfd=open(filename,O_RDONLY)) == -1)
  567.       ourexit(2,"Unknown exception file\n");
  568.  
  569.    idhead = idrefhead = NULL;   /* linked list of ID and IDREF values  */
  570.    /* in all the attribute specifications */
  571.    currexcl = currincl = NULL;  /* linked list of current exclusion */
  572.    /* and inclusion exceptions       */
  573.    stptr = NULL;  /* head pointer of input stack */
  574.  
  575.    state = GETNEW;   
  576.    sp = entitylevel = num_open_ms = 0;
  577.    open_cdata_ms = open_rcdata_ms = FALSE;
  578.    head = NULL;
  579.  
  580.    /* creates lists of general and parameter entities */
  581.    *genthead = build_entity(gentityfd);
  582.    *penthead = build_entity(pentityfd);
  583.  
  584.    *numsym = build_table(path);
  585.  
  586.    read(exceptfd,&num_elem,sizeof(int));
  587.    for (i=0; i<num_elem; i++) {        /* build list of inclusion     */
  588.       read(exceptfd,&except_elt,sizeof(int));   /* exceptions for each element */
  589.       symtable[except_elt].inclusion = build_except(exceptfd);
  590.    }
  591.    read(exceptfd,&num_elem,sizeof(int));
  592.    for (i=0; i<num_elem; i++) {         /* build list of exclusion     */
  593.       read(exceptfd,&except_elt,sizeof(int));    /* exceptions for each element */
  594.       symtable[except_elt].exclusion = build_except(exceptfd);
  595.    }
  596.  
  597.    read(attrfd,&num_elem,sizeof(int));
  598.    while(num_elem != -1) {
  599.       for (i=0; i < num_elem; i++)
  600.          read(attrfd,tokenids+i,sizeof(int));
  601.       symtable[tokenids[0]].adptr = buildattr(attrfd);
  602.       for (i=1; i < num_elem; i++)
  603.          symtable[tokenids[i]].adptr = symtable[tokenids[0]].adptr;
  604.       read(attrfd,&num_elem,sizeof(int));
  605.    }
  606.    /*  get rid of content model defined as ANY and  */
  607.    /*  build a new model, expanded out with PCDATA  */
  608.    /*  and every element in the symbol table     */
  609.    for (i=0; i < *numsym; i++)
  610.       if (symtable[i].cmptr->nodeid == ANY) {
  611.          free((char *)symtable[i].cmptr);
  612.          symtable[i].cmptr = expand_any(*numsym);
  613.       }
  614.  
  615.    qsort(symtable,*numsym,sizeof(STENTRY),compare);   /* sort the table */
  616.  
  617.    for (i=0; i < *numsym; i++) {
  618.       change_trees(symtable[i].cmptr,*numsym);
  619.       change_excepts(symtable[i].inclusion,*numsym);
  620.       change_excepts(symtable[i].exclusion,*numsym);
  621.       if (rootid==symtable[i].tokenid && !root_changed) {
  622.          root_changed = TRUE;
  623.          rootid = i;
  624.       }
  625.    }
  626.    for (i=0; i < *numsym; i++)
  627.       symtable[i].tokenid = i;
  628.  
  629.    if (close(attrfd)!=0 || close(gentityfd)!=0 ||
  630.        close(exceptfd)!=0 || close(pentityfd)!=0) {
  631.       printf("Unable to close intermediate files.\n");
  632.       exit(99);
  633.    }
  634.    return;
  635. }
  636.  
  637. /*------------------------------------------------------*/
  638. /*                C H A N G E _ R I G H T               */
  639. /* This routine is used to keep up with the  */
  640. /* flag called 'contreq' which is found on each */
  641. /* node of the content model tree.  If you are  */
  642. /* in a sequence group, and the left side wasn't   */
  643. /* found, the tag for the token found on the right */
  644. /* side should become never omissable.  If it   */
  645. /* was found on the left, the right side then   */
  646. /* becomes omissable.            */
  647. /*------------------------------------------------------*/
  648. void change_right(ptr,leftretval)
  649. TNODE *ptr;
  650. int leftretval;
  651. {
  652.    if (ptr != NULL)
  653.       if (leftretval==FOUND && ptr->contreq==C_SOMETIMESO)
  654.          if (testoi(ptr) == PLUS)
  655.             ptr->contreq = C_FTO;
  656.          else
  657.             ptr->contreq = C_ALWAYSO;
  658.       else
  659.          if (leftretval==NFDHT && ptr->contreq==C_SOMETIMESO)
  660.             ptr->contreq = C_NEVERO;
  661.    return;
  662. }
  663.